﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace LBSoft.Common.DotNetEncrypt
{
    public class DES3Helper
    {
        #region CBC模式
        /// <summary> 
        /// DES3 CBC模式加密 
        /// </summary> 
        /// <param name="key">密钥</param> 
        /// <param name="iv">IV</param> 
        /// <param name="data">明文的byte数组</param> 
        /// <returns>密文的byte数组</returns> 
        public static byte[] DES3EncodeCBC(byte[] key, byte[] iv, byte[] data)
        {
            //复制于MSDN 
            try
            {
                // Create a MemoryStream. 
                MemoryStream mStream = new MemoryStream();
                TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
                tdsp.Mode = CipherMode.CBC;             //默认值 
                tdsp.Padding = PaddingMode.PKCS7;       //默认值 
                // Create a CryptoStream using the MemoryStream  
                // and the passed key and initialization vector (IV). 
                CryptoStream cStream = new CryptoStream(mStream,
                    tdsp.CreateEncryptor(key, iv),
                    CryptoStreamMode.Write);
                // Write the byte array to the crypto stream and flush it. 
                cStream.Write(data, 0, data.Length);
                cStream.FlushFinalBlock();
                // Get an array of bytes from the  
                // MemoryStream that holds the  
                // encrypted data. 
                byte[] ret = mStream.ToArray();
                // Close the streams. 
                cStream.Close();
                mStream.Close();
                // Return the encrypted buffer. 
                return ret;
            }
            catch (CryptographicException ex)
            {
                return null;
            }
        }
        /// <summary> 
        /// DES3 CBC模式解密 
        /// </summary> 
        /// <param name="key">密钥</param> 
        /// <param name="iv">IV</param> 
        /// <param name="data">密文的byte数组</param> 
        /// <returns>明文的byte数组</returns> 
        public static byte[] DES3DecodeCBC(byte[] key, byte[] iv, byte[] data)
        {
            try
            {
                // Create a new MemoryStream using the passed  
                // array of encrypted data. 
                MemoryStream msDecrypt = new MemoryStream(data);
                TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
                tdsp.Mode = CipherMode.CBC;
                tdsp.Padding = PaddingMode.PKCS7;
                // Create a CryptoStream using the MemoryStream  
                // and the passed key and initialization vector (IV). 
                CryptoStream csDecrypt = new CryptoStream(msDecrypt,
                    tdsp.CreateDecryptor(key, iv),
                    CryptoStreamMode.Read);
                // Create buffer to hold the decrypted data. 
                byte[] fromEncrypt = new byte[data.Length];
                // Read the decrypted data out of the crypto stream 
                // and place it into the temporary buffer. 
                csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
                //Convert the buffer into a string and return it. 
                return fromEncrypt;
            }
            catch (CryptographicException ex)
            {
                return null;
            }
        }
        #endregion

        #region ECB模式
        /// <summary>
        /// DES3 ECB模式加密 
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="data">要加密的数据</param>
        /// <returns></returns>
        public static string DES3EncodeECB(string key, string data)
        {
            try
            {
                byte[] byte_key = Encoding.UTF8.GetBytes(key.Substring(0, 24));
                byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };      //当模式为ECB时，IV无用 
                byte[] byte_data = Encoding.UTF8.GetBytes(data);
                byte[] str1 = DES3EncodeECB(byte_key, iv, byte_data);
                return Convert.ToBase64String(str1);
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// DES3 ECB模式解密 
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="data">要解密的数据</param>
        /// <returns></returns>
        public static string DES3DecodeECB(string key, string data)
        {
            try
            {
                byte[] byte_key = Encoding.UTF8.GetBytes(key.Substring(0, 24));
                byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };      //当模式为ECB时，IV无用 
                byte[] byte_data = Convert.FromBase64String(data); //Encoding.UTF8.GetBytes(data);
                byte[] str2 = DES3DecodeECB(byte_key, iv, byte_data);
                return System.Text.Encoding.UTF8.GetString(str2);
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }

        /// <summary> 
        /// DES3 ECB模式加密 
        /// </summary> 
        /// <param name="key">密钥</param> 
        /// <param name="iv">IV(当模式为ECB时，IV无用)</param> 
        /// <param name="str">明文的byte数组</param> 
        /// <returns>密文的byte数组</returns> 
        public static byte[] DES3EncodeECB(byte[] key, byte[] iv, byte[] data)
        {
            try
            {
                // Create a MemoryStream. 
                MemoryStream mStream = new MemoryStream();
                TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
                tdsp.Mode = CipherMode.ECB;
                tdsp.Padding = PaddingMode.PKCS7;
                // Create a CryptoStream using the MemoryStream  
                // and the passed key and initialization vector (IV). 
                CryptoStream cStream = new CryptoStream(mStream,
                    tdsp.CreateEncryptor(key, iv),
                    CryptoStreamMode.Write);
                // Write the byte array to the crypto stream and flush it. 
                cStream.Write(data, 0, data.Length);
                cStream.FlushFinalBlock();
                // Get an array of bytes from the  
                // MemoryStream that holds the  
                // encrypted data. 
                byte[] ret = mStream.ToArray();
                // Close the streams. 
                cStream.Close();
                mStream.Close();
                // Return the encrypted buffer. 
                return ret;
            }
            catch (CryptographicException ex)
            {
                return null;
            }
        }
        /// <summary> 
        /// DES3 ECB模式解密 
        /// </summary> 
        /// <param name="key">密钥</param> 
        /// <param name="iv">IV(当模式为ECB时，IV无用)</param> 
        /// <param name="str">密文的byte数组</param> 
        /// <returns>明文的byte数组</returns> 
        public static byte[] DES3DecodeECB(byte[] key, byte[] iv, byte[] data)
        {
            try
            {
                // Create a new MemoryStream using the passed  
                // array of encrypted data. 
                MemoryStream msDecrypt = new MemoryStream(data);
                TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
                tdsp.Mode = CipherMode.ECB;
                tdsp.Padding = PaddingMode.PKCS7;
                // Create a CryptoStream using the MemoryStream  
                // and the passed key and initialization vector (IV). 
                CryptoStream csDecrypt = new CryptoStream(msDecrypt,
                    tdsp.CreateDecryptor(key, iv),
                    CryptoStreamMode.Read);
                // Create buffer to hold the decrypted data. 
                byte[] fromEncrypt = new byte[data.Length];
                // Read the decrypted data out of the crypto stream 
                // and place it into the temporary buffer. 
                csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
                //Convert the buffer into a string and return it. 
                return fromEncrypt;
            }
            catch (CryptographicException ex)
            {
                return null;
            }
        }
        #endregion
    }
}
